#include "mqtt_client.h"

#include <MQTTClient.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "message.h"

#include "cJSON.h"
#include "log.h"

static MQTTClient client = NULL;

#define server_uri ("ws://192.168.23.38:1883")
#define client_id ("test")

static void connection_lost(void *context, char *cause);
static int message_arrived(void *context, char *topicName, int topicLen,
						   MQTTClient_message *message);
static void delivery_complete(void *context, MQTTClient_deliveryToken dt);

static void display_mqtt_client_message(MQTTClient_message *message);

MQTTClient mqtt_client(void) {
	// MQTTCLIENT_PERSISTENCE_DEFAULT;
	// MQTTCLIENT_PERSISTENCE_NONE;
	// MQTTCLIENT_PERSISTENCE_USER;
	if (MQTTClient_create(&client, server_uri, client_id,
						  MQTTCLIENT_PERSISTENCE_NONE,
						  NULL) != MQTTCLIENT_SUCCESS) {
		log_error("MQTT客户端创建失败\n");
		goto mqtt_client_create_fail;
	}
	if (MQTTClient_setCallbacks(client, NULL, connection_lost, message_arrived,
								delivery_complete) != MQTTCLIENT_SUCCESS) {
		log_error("MQTT客户端设置回调函数失败\n");
		goto mqtt_client_set_callbacks_fail;
	}
	MQTTClient_connectOptions options = MQTTClient_connectOptions_initializer;
	if (MQTTClient_connect(client, &options) != MQTTCLIENT_SUCCESS) {
		log_error("MQTT客户端连接服务器失败\n");
		goto mqtt_client_connect_fail;
	}
	if (MQTTClient_subscribe(client, "服务器/#",
							 MQTTREASONCODE_GRANTED_QOS_2) !=
		MQTTCLIENT_SUCCESS) {
		log_error("MQTT客户端订阅失败\n");
		goto mqtt_client_subscribe_fail;
	}
	log_info("MQTT客户端连接服务器成功");
	return client;

mqtt_client_subscribe_fail:
	if (MQTTClient_disconnect(client, 10) != MQTTCLIENT_SUCCESS) {
		log_error("关闭MQTT客户端连接失败\n");
	}
mqtt_client_connect_fail:
mqtt_client_set_callbacks_fail:
	MQTTClient_destroy(&client);
mqtt_client_create_fail:
	return NULL;
}

static void connection_lost(void *context, char *cause) {
	log_warn("MQTT客户端失去连接");
	log_warn("content： %p, %s", context, context);
	log_warn("cause： %p, %s", cause, cause);
	exit(EXIT_FAILURE);
}
static int message_arrived(void *context, char *topicName, int topicLen,
						   MQTTClient_message *message) {
	log_info("MQTT客户端接收到消息");
	log_info("context： %p, %s", context);
	log_info("topicName： %p, %s", topicName, topicName);
	log_info("topicLen： %d", topicLen);
	display_mqtt_client_message(message);
	MQTTClient_freeMessage(&message);
	MQTTClient_free(topicName);
	return 1;
}
static void delivery_complete(void *context, MQTTClient_deliveryToken dt) {
	log_info("MQTT客户端发送消息完成");
	log_info("context：%p, %s", context);
	log_info("MQTTClient_deliveryToken：%d", dt);
}

static void display_mqtt_client_message(MQTTClient_message *message) {
	printf("消息地址 %p\n", message);
	if (!message) {
		return;
	}
	printf("%s", (char *)message->payload);
#if 0
	char *p = message->struct_id;
	printf("结构标识：%c%c%c%c\n", p[0], p[1], p[2], p[3]);
	printf("结构版本：%d\n", message->struct_version);
	printf("负载长度：%d\n", message->payloadlen);
	printf("负载内容：\n");
	int size = message->payloadlen;
	p = (char *)message->payload;
	for (int i = 0; i < size; ++i) {
		printf("\t[%03d] 0x%02x %c\n", i, p[i], isprint(p[i]) ? p[i] : '.');
	}
	printf("服务质量：%d\n", message->qos);
	printf("retained：%d\n", message->retained);
	printf("dup：%d\n", message->dup);
	printf("消息标识：%d\n", message->msgid);
	printf("属性：\n");
	printf("\t数组中属性个数：%d\n", message->properties.count);
	printf("\t当前分配数组最多能存储的属性个数：%d\n",
		   message->properties.max_count);
	printf("\t所有属性占字节数：%d\n", message->properties.length);
	size = message->properties.count;
	MQTTProperty *pro = message->properties.array;
	for (int i = 0; i < size; ++i) {
		printf("\t\t[03d] ");
	}
#endif
}
int32_t mqtt_publish(const message *message) {
	static MQTTClient_deliveryToken delivery_token = 0;
	MQTTClient_message mqtt_message = MQTTClient_message_initializer;
	// message.qos = MQTTREASONCODE_GRANTED_QOS_1;
	cJSON *json = message_to_json(NULL, message);
	char *s = cJSON_Print(json);
	mqtt_message.payload = s;
	mqtt_message.payloadlen = strlen(s);
	MQTTClient_publishMessage(client, message->topic, &message,
							  &delivery_token);
	return 0;
}